package com.ruoyi.app.controller.order.service.impl;

import com.ruoyi.app.common.utils.ApiSpaceUtils;
import com.ruoyi.app.common.utils.IdWorker;
import com.ruoyi.app.controller.marketing.mapper.IShopProductCouponLinkMapper;
import com.ruoyi.app.controller.member.mapper.IMemberCouponMapper;
import com.ruoyi.app.controller.member.mapper.IMemberCreditRecordMapper;
import com.ruoyi.app.controller.member.mapper.IMemberMapper;
import com.ruoyi.app.controller.order.mapper.IShopCreditOrderMapper;
import com.ruoyi.app.controller.order.service.IShopCreditOrderService;
import com.ruoyi.app.controller.product.mapper.IProductMapper;
import com.ruoyi.app.framework.manager.AsyncManager;
import com.ruoyi.app.framework.manager.factory.ApiAsyncFactory;
import com.ruoyi.common.constant.CouponConstants;
import com.ruoyi.common.constant.MemberCreditConstants;
import com.ruoyi.common.constant.OrderConstants;
import com.ruoyi.common.constant.SysConfigConstants;
import com.ruoyi.common.entity.BO.StatusEnumBO;
import com.ruoyi.common.entity.DO.member.MemberCouponDO;
import com.ruoyi.common.entity.DO.member.MemberCreditRecordDO;
import com.ruoyi.common.entity.DO.member.MemberDO;
import com.ruoyi.common.entity.DO.order.ShopCreditOrderDO;
import com.ruoyi.common.entity.VO.order.ShopOrderSearchVO;
import com.ruoyi.common.entity.VO.product.CreditProductVO;
import com.ruoyi.common.entity.VO.shop.ShopProductSearchVO;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.NumberUtils;
import com.ruoyi.common.utils.StringUtils;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service("ICreditOrderService")
@Slf4j
public class ShopCreditOrderServiceImpl implements IShopCreditOrderService {

    @Value("${api.adminHost}")
    private String adminHost;

    @Value("${api.exchangePath}")
    private String exchangePath;

    @Resource
    private IShopCreditOrderMapper shopCreditOrderMapper;

    @Resource
    private IMemberCouponMapper memberCouponMapper;

    @Resource
    private IProductMapper productMapper;

    @Resource
    private IMemberMapper memberMapper;

    @Resource
    private IMemberCreditRecordMapper creditRecordMapper;

    @Resource
    private IShopProductCouponLinkMapper shopProductCouponLinkMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Synchronized
    public void create(ShopCreditOrderDO createDO) {
        ShopProductSearchVO searchVO = new ShopProductSearchVO();
        searchVO.setShopId(createDO.getShopId());
        searchVO.setSystemModule(SysConfigConstants.SystemModuleEnum.CREDIT.getValue());
        searchVO.setProductId(createDO.getProductId());
        searchVO.setIsDelete(0);
        searchVO.setIsEnable(1);
        CreditProductVO productInfo = productMapper.getCreditProductDetail(searchVO);
        if (null == productInfo) {
            throw new BusinessException("该商品暂时无法兑换！");
        }
        if (0 == productInfo.getStock()) {
            throw new BusinessException("该商品已被抢光了！");
        }
        //TODO:获取会员积分
        MemberDO memberAsset = memberMapper.getAssetById(createDO.getMemberId());
        if (null == memberAsset) {
            throw new BusinessException("请先授权登录！");
        }
        createDO.setProductName(productInfo.getProductName());
        createDO.setProductSn(productInfo.getProductSn());
        createDO.setProductCoverUrl(productInfo.getCoverUrl());
        createDO.setProductUnitPrice(productInfo.getPrice().intValue());
        createDO.setProductQuantity(1);
        createDO.setOrderCost(createDO.getProductUnitPrice() * createDO.getProductQuantity());
        createDO.setPayCost(createDO.getOrderCost());
        if (memberAsset.getCredit() < createDO.getPayCost()) {
            throw new BusinessException("积分不足！");
        }
        String time = DateUtils.dateTimeNow();
        long orderId = 0L;
        try {
            orderId = IdWorker.getFlowIdWorkerInstance().nextId();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //TODO:查看商品类型
        List<Long> couponIdList = new ArrayList<>();
        if (1 == productInfo.getProductType()) {
            createDO.setExchangeCode(null);
            createDO.setOrderStatus(OrderConstants.CreditOrderStatusEnum.USE.getValue());
            //优惠券自动领取
            couponIdList = shopProductCouponLinkMapper.searchIdList(createDO.getShopId(), createDO.getProductId());
            if (couponIdList.size() > 0) {
                couponIdList.forEach(x -> {
                    MemberCouponDO memberCouponDO = new MemberCouponDO();
                    memberCouponDO.setCouponId(x);
                    memberCouponDO.setMemberId(createDO.getMemberId());
                    memberCouponDO.setMemberCouponStatus(CouponConstants.MemberCouponStatusEnum.NOT_USE.getValue());
                    memberCouponDO.setActivityId(0L);
                    memberCouponDO.setReceiveChannelDesc("来自：积分商城兑换");
                    memberCouponDO.setCreateTime(new Date());
                    memberCouponMapper.insertSelective(memberCouponDO);
                });
            }
        } else {
            createDO.setExchangeCode(NumberUtils.generateCode(8));
            createDO.setOrderStatus(OrderConstants.CreditOrderStatusEnum.UN_USE.getValue());
        }
        createDO.setId(orderId);
        createDO.setProductType(productInfo.getProductType());
        createDO.setOrderSn(OrderConstants.SnPrefix.PETROL.getValue() + time + NumberUtils.generateCode(5));
        createDO.setCreateTime(new Date());
        createDO.setCreateBy("积分商城兑换");
        shopCreditOrderMapper.insertSelective(createDO);
        //TODO:更新商品销量和库存
        productMapper.stockSubtraction(createDO.getProductId());
        productMapper.saleIncrement(createDO.getProductId());
        productMapper.shopSaleIncrement(createDO.getShopId(), createDO.getProductId());
        //TODO:会员积分变更
        Integer newCredit = memberAsset.getCredit() - createDO.getPayCost();
        MemberDO memberUpdate = new MemberDO();
        memberUpdate.setId(createDO.getMemberId());
        memberUpdate.setCredit(newCredit);
        memberMapper.updateByPrimaryKeySelective(memberUpdate);
        //TODO:积分变动
        MemberCreditRecordDO memberCreditRecordDO = new MemberCreditRecordDO();
        memberCreditRecordDO.setShopId(createDO.getShopId());
        memberCreditRecordDO.setRecordSn(OrderConstants.SnPrefix.CREDIT_MEMBER.getValue() + time + NumberUtils.generateCode(4));
        memberCreditRecordDO.setType(MemberCreditConstants.TypeEnum.SYSTEM_INSERT.getValue());
        memberCreditRecordDO.setChangeType(MemberCreditConstants.ChangeTypeEnum.DECREASE.getValue());
        memberCreditRecordDO.setLinkModel(MemberCreditConstants.LinkModelEnum.EXCHANGE.getValue());
        memberCreditRecordDO.setLinkSn(createDO.getOrderSn());
        memberCreditRecordDO.setMemberId(createDO.getMemberId());
        memberCreditRecordDO.setOldCredit(memberAsset.getCredit());
        memberCreditRecordDO.setChangeCredit(createDO.getPayCost());
        memberCreditRecordDO.setNewCredit(newCredit);
        memberCreditRecordDO.setRemark("兑换积分商城【" + productInfo.getProductName() + "】，扣除:" + createDO.getPayCost() + "分"
                + "，剩余：" + newCredit + "分");
        memberCreditRecordDO.setCreateBy("积分商城兑换");
        memberCreditRecordDO.setCreateTime(new Date());
        creditRecordMapper.insertSelective(memberCreditRecordDO);
        //刷新优惠券
        if (!couponIdList.isEmpty()) {
            AsyncManager.me().execute(ApiAsyncFactory.refreshCoupon(String.join(",", couponIdList.stream().map(x -> x + "").collect(Collectors.toList()))));
        }
    }

    @Override
    public List<StatusEnumBO> searchOrderStatusCount(Long memberId) {
        List<StatusEnumBO> orderStatusCountList = new ArrayList<>();
        StatusEnumBO statusEnumBO;
        for (OrderConstants.CreditOrderStatusEnum one : OrderConstants.CreditOrderStatusEnum.values()) {
            statusEnumBO = new StatusEnumBO();
            statusEnumBO.setStatus(one.getValue());
            statusEnumBO.setStatusDesc(one.getDesc());
            if (one.getValue() > -1) {
                statusEnumBO.setCount(shopCreditOrderMapper.countByStatus(memberId, one.getValue()));
            } else {
                statusEnumBO.setCount(shopCreditOrderMapper.countTotal(memberId));
            }
            orderStatusCountList.add(statusEnumBO);
        }
        return orderStatusCountList;
    }

    @Override
    public List<ShopCreditOrderDO> searchList(ShopOrderSearchVO searchVO) {
        searchVO.setIsDelete(0);
        searchVO.setIsEnable(1);
        List<ShopCreditOrderDO> shopOrderList = shopCreditOrderMapper.searchList(searchVO);
        return shopOrderList;
    }


    public ShopCreditOrderDO getExchangeCode(Long memberId, String orderSn) {
        Example example = new Example(ShopCreditOrderDO.class);
        Example.Criteria condition = example.createCriteria();
        condition.andEqualTo("isEnable", 1).andEqualTo("isDelete", 0);
        condition.andEqualTo("orderStatus", OrderConstants.CreditOrderStatusEnum.UN_USE.getValue());
        condition.andEqualTo("orderSn", orderSn);
        condition.andEqualTo("memberId", memberId);
        example.selectProperties("id", "orderSn", "exchangeCode", "exchangeCodeUrl");
        ShopCreditOrderDO orderInfo = shopCreditOrderMapper.selectOneByExample(example);
        if (orderInfo == null) {
            throw new BusinessException("核销商品无效！");
        }
        if (StringUtils.isEmpty(orderInfo.getExchangeCodeUrl())) {
            String exchangeUrl = adminHost + exchangePath + "/" + orderInfo.getExchangeCode();
            String url = ApiSpaceUtils.createUrlQrCode(exchangeUrl);
            orderInfo.setExchangeCodeUrl(url);
            shopCreditOrderMapper.updateByPrimaryKeySelective(orderInfo);
        }
        return orderInfo;
    }

}
